﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using H2.Streams;
using H2.Streams.Sections;
using System.Reflection;
using System.Runtime.InteropServices;
using H2;

namespace Mystery
{
    public partial class DataShifter
    {
        public static int CreateIndexSpace(MapStream map, int itemCount)
        {
            if (itemCount <= 0) throw new Exception("Shift Size Must Be Greater Than Zero!");
            
            const int TagIndexItemSize = 16;
            int shiftSize = itemCount * TagIndexItemSize;

            map.Header.IndexSize += shiftSize;
            map.RefreshCachedValues();

            IncreaseMapLength(map, shiftSize);

            int insertOffset = map.Index.TagInfoIndexOffset + ((map.Index.TagCount - 1) * TagIndexItemSize);
            MoveData(map, insertOffset, shiftSize);

            return insertOffset;
        }

        public static int CreateFileTableSpace(MapStream map, int shiftSize)
        {
            if (shiftSize <= 0) throw new Exception("Shift Size Must Be Greater Than Zero!");

            ShiftUnicodeTables(map, shiftSize);
            ShiftBitmapTable(map, shiftSize);

            map.Header.IndexOffset += shiftSize;

            IncreaseMapLength(map, shiftSize);
            map.RefreshCachedValues();

            map.Position = map.Header.FileTableOffset;
            for (int i = 0; i < (map.Index.TagCount - 1); i++)
                map.ReadNullTerminatedString();
            
            int insertOffset = (int)map.Position;
            MoveData(map, insertOffset, shiftSize);

            return insertOffset;
        }

        public static void WriteTagInfoIndexItem(MapStream map, string type, int startOffset, int size)
        {
            map.WriteReverseString(type);
            map.Write(0);//ID TODO: Create New ID
            map.Write(startOffset + map.Index.SecondaryMagic);//Pointer
            map.Write(size);
        }

        public static void WriteStrings(MapStream map, string[] tagPaths)
        {
            for (int i = 0; i < tagPaths.Length; i++)
                map.Write(tagPaths[i]);
        }

        private static void IncreaseMapLength(MapStream map, int shiftSize)
        {
            //Increase Map Size By Shift Size
            map.Stream.SetLength(map.Length + shiftSize);
            map.Header.Filesize += shiftSize;
        }

        private static void MoveData(MapStream map, int startOffset, int shiftSize)
        { 
            byte[] buffer = map.ReadBytesAt(startOffset, (int)map.Length - shiftSize - startOffset, false);
            map.WriteAt(startOffset + shiftSize, buffer, false);
            map.WriteAt(startOffset, new byte[shiftSize], false);
        }

        private static void UpdateTagInfoOffset(MapStream map, int id, int newOffset)
        {
            map.Position = map.Index.TagInfoIndexOffset;
            int tagCount = map.Index.TagCount;
            for (int i = 0; i < tagCount; i++)
            {
                map.Position += 4;
                if (map.ReadInt32() == id)
                {
                    //Write New Offset
                    map.Write(newOffset);
                    break;
                }
                map.Position += 8;
            }
        }

        private static void UpdateTagInfoSize(MapStream map, int id, int newSize)
        {
            map.Position = map.Index.TagInfoIndexOffset;
            int tagCount = map.Index.TagCount;
            for (int i = 0; i < tagCount; i++)
            {
                map.Position += 4;
                if (map.ReadInt32() == id)
                {
                    map.Position += 4;
                    //Write New Size
                    map.Write(newSize);
                    break;
                }
                map.Position += 8;
            }
        }
    }
}
